<?php

function numbersum($numb1, $numb2){

	// Casos especiais
	if(substr($numb1, 0, 1) != "-" && substr($numb2, 0, 1) == "-"){
		return numbersub($numb1, substr($numb2, 1));
	}else if(substr($numb1, 0, 1) == "-" && substr($numb2, 0, 1) != "-"){
		return numbersub($numb2, substr($numb1, 1));
	}else if(substr($numb1, 0, 1) == "-" && substr($numb2, 0, 1) == "-"){
		return "-".numbersum(substr($numb1, 1), substr($numb2, 1));
	}

	// Verifica se um dos números é float
  	$point1pos = strpos($numb1, ".");
	$point2pos = strpos($numb2, ".");
	if($point1pos !== false || $point2pos !== false )
	{
		if($point1pos === false){
     		$count1point = 0;
      		$point1pos = strlen($numb1);
    	}else
      		$count1point = strlen(substr($numb1, $point1pos+1));
  		if($point2pos === false){
      		$count2point = 0;
      		$point2pos = strlen($numb2);
    	}else
		 	$count2point = strlen(substr($numb2, $point2pos+1));

		$number1 = substr($numb1, 0, $point1pos);
		$number2 = substr($numb2, 0, $point2pos);

		if($count1point > $count2point){
			$countpoint = $count1point;
			$number1 .= substr($numb1, $point1pos+1);
			$number2 .= str_pad(substr($numb2, $point2pos+1), strlen(substr($numb1, $point1pos+1)), "0");
		}else{
			$countpoint = $count2point;
			$number2 .= substr($numb2, $point2pos+1);
			$number1 .= str_pad(substr($numb1, $point1pos+1), strlen(substr($numb2, $point2pos+1)), "0");
		}
	}else{
		$countpoint = 0;
		$number1 = $numb1;
		$number2 = $numb2;
	}

	$n1 = strlen($number1);
	$n2 = strlen($number2);

	$finalnumber = "";

	while($n1 != $n2){
		if($n1 > $n2){
			$number2 = "0".$number2;
			$n2 = strlen($number2);
		}else{
			$number1 = "0".$number1;
			$n1 = strlen($number1);
		}
	}

	$carry = 0;

	for($i=$n1-1; $i>=0; $i--){
		$sum = $number1[$i] + $number2[$i] + $carry;
		if($sum > 9){
			$carry = substr($sum, 0, 1);
			$sum = substr($sum, 1, 1);
		}else{
			$carry = 0;
		}
		$finalnumber = $sum.$finalnumber;
	}

	if($carry == "1") $carryf = "1"; else $carryf = "";
	$finalnumber = $carryf.$finalnumber;

	if($countpoint){
		$finalnumber = substr($finalnumber, 0, -$countpoint).".".substr($finalnumber, -$countpoint);
	}

	return $finalnumber;
}

function numbersub($numb1, $numb2){

	// Casos especiais
	if(substr($numb1, 0, 1) != "-" && substr($numb2, 0, 1) == "-"){
		return numbersum($numb1, substr($numb2, 1));
	}else if(substr($numb1, 0, 1) == "-" && substr($numb2, 0, 1) != "-"){
		return "-".numbersum(substr($numb1, 1), $numb2);
	}else if(substr($numb1, 0, 1) == "-" && substr($numb2, 0, 1) == "-"){
		return numbersub(substr($numb2, 1), substr($numb1, 1));
	}

	// Verifica se um dos números é float
  	$point1pos = strpos($numb1, ".");
	$point2pos = strpos($numb2, ".");
	if($point1pos !== false || $point2pos !== false )
	{
		if($point1pos === false){
     		$count1point = 0;
      		$point1pos = strlen($numb1);
    	}else
      		$count1point = strlen(substr($numb1, $point1pos+1));
  		if($point2pos === false){
      		$count2point = 0;
      		$point2pos = strlen($numb2);
    	}else
		 	$count2point = strlen(substr($numb2, $point2pos+1));

		$number1 = substr($numb1, 0, $point1pos);
		$number2 = substr($numb2, 0, $point2pos);

		if($count1point > $count2point){
			$countpoint = $count1point;
			$number1 .= substr($numb1, $point1pos+1);
			$number2 .= str_pad(substr($numb2, $point2pos+1), strlen(substr($numb1, $point1pos+1)), "0");
		}else{
			$countpoint = $count2point;
			$number2 .= substr($numb2, $point2pos+1);
			$number1 .= str_pad(substr($numb1, $point1pos+1), strlen(substr($numb2, $point2pos+1)), "0");
		}
	}else{
		$countpoint = 0;
		$number1 = $numb1;
		$number2 = $numb2;
	}

	$numb1 = $number1;
	$numb2 = $number2;

	$inv = "";

	if($numb1 > $numb2){
		$number1 = $numb1;
		$number2 = $numb2;
	}else{
		$inv = "-";
		$number1 = $numb2;
		$number2 = $numb1;
	}

	$n1 = strlen($number1);
	$n2 = strlen($number2);

	$finalnumber = "";

	while($n1 != $n2){
		if($n1 > $n2){
			$number2 = "0".$number2;
			$n2 = strlen($number2);
		}else{
			$number1 = "0".$number1;
			$n1 = strlen($number1);
		}
	}

	//echo "number1 = $number1<br><br>";
	//echo "number2 = $number2<br><br>";

	$carry = 0;

	for($i=$n1-1; $i>=0; $i--){
		//echo "number1[$i] = $number1[$i]<br><br>";
		//echo "number2[$i] = $number2[$i]<br><br>";
		if($number1[$i] >= $number2[$i]){
			$sub = $number1[$i] - $number2[$i];
			//echo "sub = $number1[$i] - $number2[$i] = $sub<br><br>";
		}else{
			//echo "aqui<br>";
			$k = $i-1;
			while($number1[$k] == 0){
				$number1[$k] = 9;
				$k--;
			}
			$number1[$k] = $number1[$k]-1;
			//echo "novo number1 = $number1<br>";
			$sub = 10 + $number1[$i] - $number2[$i];
			//echo "sub = 10 + $number1[$i] - $number2[$i] = $sub<br><br>";
		}
		//echo "number1 = $number1<br><br>";
		//echo "number2 = $number2<br><br>";
		$finalnumber = $sub.$finalnumber;
	}

	$checknumber = $finalnumber;
	$nfn = strlen($finalnumber);
	$iszero = true;

	for($i=0; $i<$nfn; $i++){
		if($checknumber[$i] != "0"){
			$iszero = false; break;
		}else{
			$finalnumber = substr($finalnumber, 1);
		}
	}

	$finalnumber = $iszero ? "0" : $inv.$finalnumber;
	//echo "finalnumber = $finalnumber<br>";

	if($countpoint){
		if(substr($finalnumber, 0, -$countpoint) == "") $pre = "0"; else $pre = substr($finalnumber, 0, -$countpoint);
		$finalnumber = $pre.".".substr($finalnumber, -$countpoint);
	}

	return $iszero ? "0" : $finalnumber;
}

function numbermult($numb1, $numb2){

	// Casos especiais
	if($numb1 == "0" || $numb2 == "0"){
		return "0";
	}
	else if($numb1 == "1"){
		return $numb2;
	}
	else if($numb2 == "1"){
		return $numb1;
	}
	else if($numb1 == "-1"){
		if(substr($numb2, 0, 1) == "-")
			return substr($numb1, 1);
		else
			return "-".$numb1;
	}
	else if($numb2 == "-1"){
		if(substr($numb1, 0, 1) == "-")
			return substr($numb1, 1);
		else
			return "-".$numb1;
	}

	// Mantém o sinal de negativo
	$inv = "";

	if(substr($numb1, 0, 1) == "-" || substr($numb2, 0, 1) == "-"){
		if((substr($numb1, 0, 1) == "-") ^ (substr($numb2, 0, 1) == "-")) $inv = "-";
		if(substr($numb1, 0, 1) == "-") $numb1 = substr($numb1, 1);
		if(substr($numb2, 0, 1) == "-") $numb2 = substr($numb2, 1);
	}

	// Verifica se um dos números é float
  	$point1pos = strpos($numb1, ".");
	$point2pos = strpos($numb2, ".");
	if($point1pos !== false || $point2pos !== false )
	{
		if($point1pos === false){
     		$count1point = 0;
      		$point1pos = strlen($numb1);
    	}else
      		$count1point = strlen(substr($numb1, $point1pos+1));
  		if($point2pos === false){
      		$count2point = 0;
      		$point2pos = strlen($numb2);
    	}else
		 	$count2point = strlen(substr($numb2, $point2pos+1));

		$number1 = str_replace(".", "", $numb1);
		$number2 = str_replace(".", "", $numb2);

		$countpoint = $count1point + $count2point;
	}else{
		$countpoint = 0;
		$number1 = $numb1;
		$number2 = $numb2;
	}

	$n1 = strlen($number1);
	$n2 = strlen($number2);

	$finalnumber = "";
	$buffernumber = "0";

	$carry = 0;

	for($i=$n1-1; $i>=0; $i--){
		for($j=$n2-1; $j>=0; $j--){
			//echo "number1[$i] = $number1[$i] <br><br>";
			//echo "number2[$j] = $number2[$j] <br><br>";
			$mult = $number1[$i] * $number2[$j] + $carry;
			if($mult > 9){
				$carry = substr($mult, 0, 1);
				$mult = substr($mult, 1, 1);
				//echo "carry = $carry <br><br>";
				//echo "mult = $mult <br><br>";
			}else{
				$carry = 0;
				//echo "carry = $carry <br><br>";
				//echo "mult = $mult <br><br>";
			}
			$finalnumber = $mult.$finalnumber;
		}
		if($carry > 0){
			$finalnumber = $carry.$finalnumber;
		}
		$carry = 0;
		$k = 0;
		while($k != ($n1-1-$i)){
			$finalnumber .= "0";
			$k++;
		}
		//echo "finalnumber = ".$finalnumber."<br><br>";
		//echo "buffernumber = numbersum($buffernumber, $finalnumber)<br><br>";
		$buffernumber = numbersum($buffernumber, $finalnumber);
		$finalnumber = "";
		//echo "buffnumber".$buffernumber."<br><br>";
	}

	if($countpoint){
		$buffernumber = substr($buffernumber, 0, -$countpoint).".".substr($buffernumber, -$countpoint);
	}

	return $inv.$buffernumber;
}

// Antigo numberpow
function oldnumberpow($number1, $number2){

	$finalnumber = $number1;
	//echo "number2 = $number2 <br><br>";
	
	for($i=1; $i<$number2; $i++){
		$finalnumber = numbermult($finalnumber, $number1);
	}

	return $finalnumber;
}

function numberpow($number1, $number2){

	// Casos especiais
	if($number2 == "0"){
		return "1";
	}else if($number1 == "1"){
		return "1";
	}else if($number1 == "-1"){
		if(substr($number2, -1)%2 == 0){
			return "1";
		}else{
			return "-1";
		}
	}else if(substr($number2, 0, 1) == "-"){
		return numberdiv("1", numberpow($number1, substr($number2, 1)));
	}else if(substr($number1, 0, 1) == "-"){
		if(substr($number2, -1)%2 == 0){
			return numberpow(substr($number1, 1), $number2);
		}else{
			return "-".numberpow(substr($number1, 1), $number2);
		}
	}

	$bin = decbin($number2);
	$binlen = strlen($bin);
	$finalnumber = "1";
	$lastnumber = "1";
	//echo "number2 = $number2 <br><br>";
	
	for($i=$binlen-1; $i>=0; $i--){
		if($i == ($binlen-1))
			$lastnumber = $number1;
		else
			$lastnumber = numbermult($lastnumber, $lastnumber);
		if($bin[$i] == "1"){
			$finalnumber = numbermult($finalnumber, $lastnumber);
		}
	}

	return $finalnumber;
}

function numberpow_newton($number1, $number2){
	
	$point2pos = strpos($number2, ".");
	$count2point = strlen(substr($number2, $point2pos+1));
	$powerinx = str_pad("10", $count2point+1, "0");
	$powerinnum = $powerinx * $number2;

	//Teste
	//$powerinx = "2";
	//$powerinnum = "1";

	echo "powerinx = $powerinx<br>";
	echo "powerinnum = $powerinnum<br>";

	$x = "1";
	$pow2 = numberpow($number1, $powerinnum);
	echo "$number1 ^ $powerinnum = $pow2<br>";
	$sub1 = numbersub($powerinx, "1");
	//echo "porra".$sub1."a";

	for($i=0; $i<50; $i++){
		$x = numbersub($x, numberdiv(numbersub(numberpow($x, $powerinx), $pow2) ,numbermult($powerinx, numberpow($x, $sub1))));
	}

	return $x;

}

/*
function oldnumberdiv($numb1, $numb2){

	$finalnumber = "";
	$point = false;

	$number1 = $numb1;
	$number2 = $numb2;

	$n2 = strlen($number2);

	while($number1 < $number2){
		if(!$point){
			$finalnumber .= "0.";
			$point = true;
		}else{
			$finalnumber .= "0";
		}
		$number1 .= "0";
	}

	//echo "number1 = $number1<br><br>";
	//echo "number2 = $number2<br><br>";
	$Max = 5;
	$j = 0;

	while($number1 != "0" && $j < $Max){
		$j++;
		$i = 0;

		while(substr($number1, 0, $n2+$i) < $number2){
			$i++;
		}
		
		echo "i = $i <br><br>";
		$get = substr($number1, 0, $n2+$i);
		$nget = strlen($get);
		echo "get = $get <br><br>";
		
		$m = 9;

		while(substr(numbersub($get, numbermult("".$m."", $number2)), 0, 1) == "-"){
				//echo "numbermult($m, $number2) = ".numbermult("".$m."", $number2)."<br><br>";
				//echo "numbersub($get, numbermult($m, $number2)) = ".numbersub($get, numbermult("".$m."", $number2))."<br><br>";
				//echo "substr(numbersub($get, numbermult($m, $number2)) = ".substr(numbersub($get, numbermult("".$m."", $number2)), 0, 1)."<br><br>";
				//echo "m = $m<br><br>";
			$m--;
		}

		if(strlen($number1) == $nget){
			$get = numbersub($get, numbermult("".$m."", $number2));
			$number1 = $get."0";
			if($point == false){
				$finalnumber .= $m.".";
				$point = true;
			}else{
				$finalnumber .= $m;
			}
			
		}else{
			$get = numbersub($get, numbermult("".$m."", $number2));
			echo "get = numbersub($get, numbermult($m, $number2)) = $get";
			$number1 = $get.substr($number1, $n2+$i);
			$finalnumber .= $m;
		}
	}


	return $finalnumber;
}
*/

function numberdiv($numb1, $numb2){

	// Casos especiais
	if($numb2 == "0") throw new Exception('Division by zero.');
	else if($numb2 == "1") return $numb1;
	else if($numb2 == "-1"){
		if(substr($numb1, 0, 1) == "-")
			return substr($numb1, 1);
		else
			return "-".$numb1;
	}

	// Mantém o sinal de negativo
	$inv = "";

	if(substr($numb1, 0, 1) == "-" || substr($numb2, 0, 1) == "-"){
		if((substr($numb1, 0, 1) == "-") ^ (substr($numb2, 0, 1) == "-")) $inv = "-";
		if(substr($numb1, 0, 1) == "-") $numb1 = substr($numb1, 1);
		if(substr($numb2, 0, 1) == "-") $numb2 = substr($numb2, 1);
	}

	// Verifica se um dos números é float
  	$point1pos = strpos($numb1, ".");
	$point2pos = strpos($numb2, ".");
	if($point1pos !== false || $point2pos !== false )
	{
		if($point1pos === false){
     		$count1point = 0;
      		$point1pos = strlen($numb1);
    	}else
      		$count1point = strlen(substr($numb1, $point1pos+1));
  		if($point2pos === false){
      		$count2point = 0;
      		$point2pos = strlen($numb2);
    	}else
		 	$count2point = strlen(substr($numb2, $point2pos+1));

		$number1 = substr($numb1, 0, $point1pos);
		$number2 = substr($numb2, 0, $point2pos);

		if($count1point > $count2point){
			$number1 .= substr($numb1, $point1pos+1);
			$number2 .= str_pad(substr($numb2, $point2pos+1), strlen(substr($numb1, $point1pos+1)), "0");
		}else{
			$number2 .= substr($numb2, $point2pos+1);
			$number1 .= str_pad(substr($numb1, $point1pos+1), strlen(substr($numb2, $point2pos+1)), "0");
		}
	}else{
		$number1 = $numb1;
		$number2 = $numb2;
	}

	$finalnumber = "";
	$point = false;

	$countnumber1 = strlen($number1);
	$countnumber2 = strlen($number2);
	$numbercheck = substr($number1, 0, $countnumber2);
	//echo "number1 = $number1<br>";
	//echo "number2 = $number2<br>";
	//echo "numbercheck = $numbercheck<br>";

	$Max = 10;
	$j = 0;
	$stop = false;

	$mults = array(numbermult("1", $number2), numbermult("2", $number2),
				   numbermult("3", $number2), numbermult("4", $number2),
				   numbermult("5", $number2), numbermult("6", $number2),
				   numbermult("7", $number2), numbermult("8", $number2),
				   numbermult("9", $number2));

	$istart = $countnumber2;
	$ilen = 0;

	while(($numbercheck != "0" || !$stop) && $j < $Max){
		$j++;

		//echo "numbercheck = ".$numbercheck."<br>";
		//echo "istart = $istart<br>";
		//echo "ilen = $ilen<br>";

		if($istart + $ilen > $countnumber1){
			$stop = true;
		}

		if(!$stop){
			$first = false;
			while($numbercheck.substr($number1, $istart, $ilen) < $number2 && ($istart + $ilen) <= $countnumber1){
				//echo "numbercheck.substr = ".$numbercheck.substr($number1, $istart, $ilen)."<br>";
				if($first) $finalnumber .= "0";
				$ilen++;
				$first = true;
			}
		}else{
			$istart = 0;
			$ilen = 0;
			$first = false;
			while($numbercheck < $number2){
				//echo "while($numbercheck < $number2)<br>";
				//echo "point = $point<br>";
				if($point){
					//echo "numbercheck = $numbercheck<br>";
					//echo "finalnumber = $finalnumber<br>";
					$numbercheck .= "0";
					if($first || $finalnumber == "0."){
						$finalnumber .= "0";
					}
					//echo "numbercheck = $numbercheck<br>";
					//echo "finalnumber = $finalnumber<br>";
					$first = true;
				}else{
					$point = true;
					//echo "numbercheck = $numbercheck<br>";
					//echo "finalnumber = $finalnumber<br>";
					if($finalnumber == "") $finalnumber .= "0."; else{ $finalnumber .= "."; $first = true;}
					$numbercheck .= "0";
					//echo "numbercheck = $numbercheck<br>";
					//echo "finalnumber = $finalnumber<br>";
				}
			}
		}

		////echo "finalnumber = $finalnumber<br>";

		//echo "numbercheck.substr = ".$numbercheck.substr($number1, $istart, $ilen)."<br>";
		//echo "ilen2 = $ilen<br>";

		if($istart + $ilen >= $countnumber1){
			$stop = true;
		}

		//echo "stop = $stop<br>";
		$get = $numbercheck.substr($number1, $istart, $ilen);
		$nget = strlen($get);

		$m = 9;

		while($m != 0 && substr(numbersub($get, $mults[$m-1]), 0, 1) == "-"){
			$m--;
		}

		//echo "m = $m<br>";

		//echo "get = $get<br>";
		if($m != 0){ $get = numbersub($get, $mults[$m-1]);
		//echo "numbermult($m, $number2) = ".$mults[$m-1]."<br>";
		}
		//echo "get = numbersub($get, numbermult($m, $number2)) = $get<br>";
		$numbercheck = $get;
		$finalnumber .= $m;
		$istart = $istart+$ilen;
		$ilen = 1;
		//echo "istart = $istart<br>";
		//echo "ilen = $ilen<br>";
		//echo "<hr>";

	}

	return $inv.$finalnumber;

}

//echo numberpow("3", "74859")."<br><br>";
//$a = microtime(true);
//echo numberpow("3", "2.5")."<br>";
//$a = microtime(true) - $a;
//$b = microtime(true);
//echo oldnumberpow("3", "40")."<br>";
//$b = microtime(true) - $b;
//echo $a." - ".$b."<br>";
//echo ($a/$b);
//echo numbersum("146721", "900000");
//echo numbersub("405", "376");
//$a = numberdiv("5105","47");
//$b = 5105/47;
//echo $a." - ".$b;


/*$i = 0;
while($i < 30){
	$a1 = rand(1, 3000);
	$b1 = rand(1, 3000);
	//$a = numberdiv("".$a1."","".$b1."");
	//$b = $a1/$b1;
	$a = numbersub("".$a1."","".$b1."");
	$b = $a1-$b1;
	if(substr($a, 0,13) == substr($b, 0,13)) echo "AA AAAAA"; else '<font color="red">SE FODEU</font> ';
	echo $a1."-".$b1." ".$a." - ".$b."<br>";
}*/

/*
$a = numberdiv("2836","572");
$b = 2836/572;
echo $a." - ".$b."<br>";

$a = numberdiv("1167","1065");
$b = 1167/1065;
echo $a." - ".$b."<br>";

$a = numberdiv("2","500");
$b = 2/500;
echo $a." - ".$b."<br>";
*/


//$a = numberpow_newton("3", "0.8");
//$a = numbersub("3","5");
//$b = (3)-(5);
//echo $a." = ".$b;
//echo numbermult("9", "47");

// Pi
/*$serie = "0";
for($n=0; $n<1000; $n++){
	$q = $n%2 == 0 ? "1" : "-1";
	$div = numberdiv($q, "".(2*$n+1)."");
	$serie = numbersum($serie, $div);
	echo "div = $q / ".(2*$n+1)." = $div";
	echo "<hr>";
}*/


//echo numbermult("4", $serie);

//echo "<br>";
echo numberpow_newton("2","0.5")."<br>";
echo pow(2,0.5);
/*$serie = 0;
for($n=0; $n<1000; $n++){
	$serie += pow(-1,$n)/(2*$n+1);
}

echo 4*$serie;*/

//echo numberdiv("62832","20000");

?>